/*
 * Copyright 2010 Mark Watkinson
 * 
 * This file is part of Luminous.
 * 
 * Luminous is free software: you can redistribute it and/or
 * modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 * 
 * Luminous is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 * 
 * You should have received a copy of the GNU General Public License
 * along with Luminous.  If not, see <http://www.gnu.org/licenses/>.
 */




var $Luminous = jQuery;

var luminous_version = "0.3.1";
var luminous_date = "11/11/10";

var luminous_initialised = false;
var luminous_fixed_bar = false;



var metabar_buttons = '<span class="metabar_buttons">\
<a href=# class="link luminous_uncollapse_clicker" title="Expand">\
&nbsp;</a>\
<a href=# class="link luminous_search_clicker" title="Search">\
&nbsp;</a>\
<a href=# class="link zoomout luminous_zoomout_clicker" title="Font size--">\
&nbsp;</a>\
<a href=# class="link zoomin luminous_zoomin_clicker" title="Font size++">\
&nbsp;</a>\
<a href=# class="link unhighlight luminous_plain_clicker" title="Toggle \
Highlighting">&nbsp;</a>\
<a href=# class="link print luminous_print_clicker" title="Print">&nbsp;</a>\
<a href=# class="link info luminous_info_clicker" title="Highlighting info">\
&nbsp;</a>\
</span>';


function luminous_exp_collapse(luminous)
{
  cc = $Luminous('div.code_container', luminous);
  $Luminous('.luminous_uncollapse_clicker', luminous).toggleClass('luminous_collapse_clicker');
  
  
  if (luminous.data('collapsed'))
  { 
    cc.css('max-height', luminous.data('max-height'));
    luminous.data('collapsed', false);
    cc.css('overflow', 'auto');
    $Luminous('.luminous_uncollapse_clicker', luminous).attr('title', 'Expand');
    
    
  }
  else
  {
    luminous.data('max-height', cc.css('max-height'));
    luminous.data('collapsed', true);
    cc.css('max-height', 'none');
    cc.css('overflow', 'visible');
    $Luminous('.luminous_uncollapse_clicker', luminous).attr('title', 'Collapse');
    
    
  }
}

function luminous_search_open(luminous)
{
  $Luminous(luminous).data('search_index', 0);
  var search = $Luminous('<input type="text" class="luminous_search"></input>');
  var search_container = $Luminous('<div class="luminous_search_container">\
  <a href=# class="link luminous_close_search_clicker luminous_clicker">&nbsp</a></div>');
  
  $Luminous('.luminous_close_search_clicker', search_container).click(
    function() { luminous_close_search(luminous_root(this)); 
      return false;
    });
  
  search.keypress(function(e){
    if (e.keyCode == 13)
      luminous_search_submit(luminous_root($Luminous(this)), this.value)
    else if(e.keyCode == 27)
      luminous_close_search(luminous_root($Luminous(this)));
    return true;
  });
  var pos = luminous_get_tr_position(luminous);
  pos.left -= 15;
  pos.top += 35;
  search_container.prepend(search);
  
  search.css('width', '98px'); //2 for border
//   search_container.css('width', '100px');
  luminous.prepend(search_container);  
  
  search_container.css('left', (pos.left - search_container.width()) + 'px').css('top', pos.top + 'px');
  
  var x = search_container.width();
  search.focus();
}

function _luminous_search()
{
  var element = $Luminous('.luminous_active_search');
  if (!element.length)
    return;
  var luminousroot = luminous_root(element);
  var search_data = element.data('search_data');
  var starti = search_data.i;  
  while (search_data.i < search_data.html.length && search_data.i - starti < 1024*10)
  {
    var c = search_data.html.charAt(search_data.i);
    var remaining = search_data.html.substr(search_data.i);
    if (c == '<')
    {
      var x = remaining.search('>') + 1;
      if (!search_data.matching)
        search_data.html_new += remaining.substr(0, x);
      search_data.i+=x;
      continue;
    }
    else if (c == '&')
    {
      var x = remaining.search(';') + 1;
      if (!search_data.matching)
        search_data.html_new += remaining.substr(0, x);
      search_data.i+=x;
      continue;
    }
    
    if (!search_data.matching && search_data.searchstr.charAt(0) != c)
    {
      var next = remaining.indexOf(search_data.searchstr.charAt(0));
      if (next == -1)
      {
        search_data.html_new += remaining;
        search_data.i = search_data.html.length;
        break;
      }
      var r2 = remaining.substr(next);
      var close = r2.indexOf('>');
      var open = r2.indexOf('<');
      
      var next_i = next;
      
      if (
        (close != -1 && open == -1)
        |
        (close != -1 && open != -1 && close < open)
      )
        next_i = next + close;
        
      var abs_i = search_data.i + next_i;
      var min = Math.max(0, abs_i-5)
      var preceding = search_data.html.substr( min, abs_i-min);
      if (preceding.search(/&[^;]*$/) != -1)
        next_i = next + r2.search(';'); 
      
      search_data.i += next_i;
      search_data.html_new += remaining.substr(0, next_i);
      continue;
    }
    
    match_len = search_data.sub_match.length;
    var failed = false;
    if (!search_data.matching)
    {
      if (c == search_data.searchstr.charAt(0))
      {
        search_data.open = search_data.i;
        search_data.sub_match = c;
        search_data.matching = true;
      }
    }
    else if (search_data.matching)
    {
      if (c == search_data.searchstr.charAt(match_len))
      {
        search_data.sub_match += c;
        search_data.matching = true;
      }
      else
      {
        failed = true;
        search_data.matching = false;
      }
    }
    
    if (search_data.matching)
    {
//       alert("matching " + search_data.sub_match);
      if (search_data.sub_match.length == search_data.searchstr.length)
      {
        var subtext = search_data.html.substr(search_data.open, search_data.i+1-search_data.open);
        subtext = subtext.replace(/(<span.*?>)/gi, "</hl>$1<hl>");
        subtext = subtext.replace(/(<\/span.*?>)/gi, "</hl>$1<hl>");
        subtext = subtext.replace(/<hl>/g, "<span class='user_highlight'>");
        subtext = subtext.replace(/<\/hl>/g, "</span>");
        var replace = "<span class='user_highlight'>" + subtext + "</span>";
        search_data.html_new += replace;
        search_data.sub_match = "";
        search_data.matching = false;
      }
    }
    else if (failed)
    {
      var subtext = search_data.html.substr(search_data.open, search_data.i-search_data.open);
      search_data.html_new += subtext;
      search_data.html_new += c;
      search_data.sub_match = "";
      search_data.matching = false;
    }
    else 
    {
      search_data.html_new += c;
    }
    
    search_data.i++;
  }
  if (search_data.i >= search_data.html.length)    
  {    
//     alert(search_data.html_new);
    // because IE is stupid
    var select = (search_data.plain)? 'plain' : 'highlighted';
    $p = $Luminous('pre.' + select, luminousroot).parent();
    $new = $Luminous('<pre class="code ' + select + '">' + search_data.html_new + '</pre>');
    $Luminous('pre.' + select, luminousroot).replaceWith($new);
    
//     $p.prepend($new);
    $Luminous('div.searching', luminousroot).remove();
    element.toggleClass('luminous_active_search');
  }
  else
  {
    $Luminous('span.search_progress', luminousroot).html(
      Math.round(search_data.i/search_data.html.length * 100) + "%");
   
    $Luminous('.luminous_search_container', luminousroot).data('search_data', search_data);
    setTimeout(function() { _luminous_search(); }, 100);
  }
}
  

function luminous_search_submit(luminous, searchstr)
{
  luminous_search_reset(luminous);
  searchstr = searchstr.replace(/&/g, '&amp;');
  searchstr = searchstr.replace(/</g, '&lt;');
  searchstr = searchstr.replace(/>/g, '&gt;');
  var plain = luminous.data('code_view') == 'plain';
//   alert(searchstr);
  if (!searchstr.length)
    return;
  var search_data = 
  {
    i:0,
    plain : plain,
    html:  (plain)? $Luminous('pre.plain', luminous).html() : 
      $Luminous('pre.highlighted', luminous).html(),
    html_new : "",
    sub_match : "",
    open : 0,
    matching : false,  
    searchstr : searchstr
  };
//   alert(search_data.plain);
  
  $Luminous('.luminous_search_container', luminous).toggleClass('luminous_active_search').append(
    $Luminous('<div class="searching"><span class="search_progress"></span> <a href="#" class="luminous_search_cancel">Cancel</a></div>'));
  $Luminous('.luminous_search_container', luminous).data('search_data', search_data);
  
  $Luminous('.luminous_search_cancel', luminous).click(function(){
    var root = luminous_root(this);
    $Luminous('.luminous_active_search', root).toggleClass('luminous_active_search');
    $Luminous('div.searching', root).remove();
    luminous_close_search(root);
    return false;
  });  
  
  _luminous_search();
}

function luminous_search_reset(luminous)
{
  $Luminous('.luminous_active_search').toggleClass('luminous_active_search');
  $Luminous('.user_highlight', luminous).each( function(i, e){
    $Luminous(e).replaceWith($Luminous(e).html())
  });
}

function luminous_close_search(luminous)
{
  luminous_search_reset(luminous);
  $Luminous('.luminous_search_container', luminous).fadeOut(250,
    function (){ $Luminous(this).remove() }
  );
}


function luminous_show_info(luminous)
{  
  
  var l = $Luminous('.luminous_info', $Luminous(luminous));
  
  if (!l.length)
    luminous_attach_infopane(luminous);
  $Luminous('.luminous_info', $Luminous(luminous)).fadeIn(500);   
  return false; 
}

function luminous_close_info(luminous)
{

  
  if ($Luminous.browser.msie)
    $Luminous('.luminous_info', $Luminous(luminous)).hide();
  else
    $Luminous('.luminous_info', $Luminous(luminous)).fadeOut(500);
  luminous_show_buttons(luminous);
  return false; 
}


function luminous_get_tr_position(luminous)
{
  var luminous_pos = luminous.offset();
  
  var parents = $Luminous(luminous).parents();  
  for (var i=0; i<parents.length; i++)
  {
    var p = $Luminous(parents[i]);
    if (p.is('body'))
      break;
    var top = p.scrollTop();
    luminous_pos.top += top;
  }
  var st =  $Luminous(window).scrollTop(); 
  luminous_pos.top -= st;
  
  var luminous_width = luminous.width();
  var offset = luminous_pos;
  
  offset.left = luminous_pos.left += luminous_width;
  offset.left -= $Luminous(window).scrollLeft();
  
  offset.top = Math.max(offset.top, 0);  
  return offset;
}

function luminous_show_buttons(luminous)
{
  if (luminous_fixed_bar)
    return;
  // IE as usual doesn't work
  if ($Luminous.browser.msie && $Luminous.browser.version <= 7)
  {
    $Luminous('.metabar_buttons', luminous).css('position', 'absolute').css('right', '5px');
  }
  else
  {

    var metabar_width = $Luminous('.metabar_buttons', luminous).width();
    var offset = luminous_get_tr_position(luminous);
    
    offset.top += 10;
    offset.left -= metabar_width + 15;
    
    $Luminous('.metabar_buttons', luminous).css('top', offset.top + 'px').css('left', offset.left + 'px');
  }
  $Luminous('.metabar_buttons', luminous).show();
  
}
function luminous_hide_buttons(luminous)
{
  if (luminous_fixed_bar)
    return;
  $Luminous('.metabar_buttons', luminous).fadeOut(100);
}

function luminous_toggle_plain(luminous)
{
  var code = $Luminous('pre.highlighted', luminous).filter(function(x){ return !$Luminous(this).hasClass('plain')} );
  
  if (!$Luminous('pre.plain', luminous).length)
  {
    var content = code.html();
    var plain = content.replace(/<.*?>/ig, "");
    // Creating the pre element with full contents works around an IE bug
    // where white space isn't re-evaluated for changing content.
    $Luminous('pre.code', luminous).parent().prepend($Luminous('<pre class="code plain">'
      + plain + '</pre>').hide());
  }
  // filter to just the code object
  plain = $Luminous('pre.plain', luminous);
  $Luminous('.luminous_plain_clicker', luminous).toggleClass('highlight unhighlight');
  
  /* The transition looks better faded, but text fading has some caveats with
   * IE so for IE we go with the simpler option */
  if (1 || $Luminous.browser.msie)
  {    
    if ($Luminous(code).css('display') == 'none')
      luminous.data('code_view', 'highlighted');
    else
      luminous.data('code_view', 'plain');
    code.add(plain).toggle();
    return;
  }
  
  var cb = function(){$Luminous(this).css('position', 'relative')};
  plain.css('position', 'absolute');
  code.css('position', 'absolute');
  if ($Luminous(code).css('display') == 'none')
  {
    code.fadeIn(500, cb);
    plain.fadeOut(500);
    luminous.data('code_view', 'highlighted');
  }
  else
  {
    code.fadeOut(500);
    plain.fadeIn(500, cb);
    luminous.data('code_view', 'plain');
  }
}

function luminous_root(element)
{
  while (element != [] && !$Luminous(element).hasClass('luminous'))
    element = $Luminous(element).parent();
  return element;
}


function luminous_print_arrange_numbered(element)
{
  var $linenos = $Luminous('span.line_number', $Luminous(element));
  var line_nos_text = "";  
  for (var i=0; i<$linenos.length; i++)
    line_nos_text += $Luminous($linenos[i]).html().replace(/<.*?>/g, "") + "\n";
  
  var lines_text = "";
  var $lines = $Luminous('span.line', $Luminous(element));  
  for (var i=0; i<$lines.length; i++)
    lines_text += $Luminous($lines[i]).html() + "\n";
  
  var table = "<ol>";
  var lines = lines_text.split("\n");
  var line_nos = line_nos_text.split("\n");
  
  var len_lines = lines.length;
  var len_line_nos = line_nos.length;
  
  for (var i=0; i<len_lines; i++)
  {
    table += "<li style='white-space:pre-wrap;'>" + lines[i];
    var j = i+1;
    var x;
    while (j<len_lines && (x = line_nos[j].match(/\d+/)) == null)
    {
      table += lines[j++];
      i++;
    }
    table += "</li>";
  }
  table += "</ol>";
  return table;
}

function luminous_print_arrange_non_numbered(element)
{
  return $Luminous('pre.code', $Luminous(element)).html();
}

function luminous_print(element)
{
  var html = '<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">';
  html += "<html>\n<head>\n";
  var title = $Luminous("title");
  if ($Luminous("title"))
    html += "<title>" + $Luminous("title").html() + "</title>\n";
  // Have to grep for the stylesheets to include
  var stylesheets = $Luminous('link');  
  // URI to the light theme. This is used as the print theme, because 
  // printing background colours is a user option, so we just want to go with
  // a white background theme. ie, luminous_light.
  // we guess the URI via the luminous.css URI
  var href_to_theme = "";  
  for(var i=0; i<stylesheets.length; i++)
  {
    var href = stylesheets[i].href;
    if (href.match(/\/luminous.css$/))
      href_to_theme = href.replace(/\/luminous.css$/, "/luminous_light.css");
    // not interested in other styles
    else 
      continue;
    html += "<link rel='stylesheet' type='text/css' href='" 
            + stylesheets[i].href + "'>\n";
  }
  html += "<link rel='stylesheet' type='text/css' href='" + href_to_theme + 
  "'>";
  html += "<link rel='stylesheet' type='text/css' href='" + href_to_theme.replace(/_light.css$/, '_print.css') + 
  "'>";
  html += "<style type='text/css'>div.luminous { font-size: " + $Luminous(element).css('font-size') + " !important;}</style>";
  html += "</head>\n<body onload='window.print();'>\n";
  
  html += "<div class='luminous'>";
  
  
 
  var lines;
  lines = $Luminous('td.line_numbers', $Luminous(element)).length? 
    luminous_print_arrange_numbered(element) : 
    luminous_print_arrange_non_numbered(element);
    
  var $el = $Luminous(element).clone();
  $cc_contents = $Luminous('<pre class=code>' + lines + '</pre>');
  $Luminous('div.code_container', $el).html($cc_contents);
  $Luminous('div.code_container', $el).css('max-height', 'none');
    
  html += $el.html();
  html += "</div></body>\n</html>\n";
  
  var w = window.open();
  var e = $Luminous(html);
  w.top.document.open();
  w.top.document.write(html);
  w.document.close();
}

function luminous_get_info_element(condensed)
{
  var element;
  if (condensed === true)
  {
    element = $Luminous("<span class='code luminous_info'>\
    Highlighting peformed by Luminous.\
    <a class=link href='http://www.asgaard.co.uk/p/Luminous' \
    target=_blank>More info</a> | <a href=# class='luminous_info_close link'>\
    Close</a></span>");
  }
  else
  {
    element = $Luminous("<span class='luminous_info code'>\
    <h1 style='text-align:center; margin-top:0;' class='keyword'>\
    Luminous " + luminous_version + 
  " " + luminous_date + " </h1>\
  <p>This source was highlighted with <span class='keyword'>Luminous</span>. Visit \
  <a class=link href='http://code.google.com/p/luminous/' target=_blank>\
  http://code.google.com/p/luminous/</a> for the latest \
  stable and development versions, and \
  <a class=link \
  href=http://www.asgaard.co.uk/p/Luminous \
  target=_blank>\
  http://www.asgaard.co.uk/p/Luminous</a>\
  for more information</p>\
    <p><span class='keyword'>Luminous</span> is free software (GPL)</p>\
    <p><span class='comment'>&copy; 2010 Mark Watkinson\
    <em>&lt;markwatkinson@gmail.com&gt;</em></span></p>\
    <p><a href=# class='luminous_info_close link'\
    >Close</a></p>\
    </span>"
    );
  }
  $Luminous('.luminous_info_close', element).click( function(e){
    luminous_close_info((luminous_root((e.target))));
    return false;
  });    
  return element;
}


function luminous_attach_infopane(luminous)
{
  $Luminous(luminous).prepend(
    luminous_get_info_element($Luminous(luminous).height() < 100)
  );
 

}


function luminous_determine_id(target)
{
  while (target && !$Luminous(target).hasClass('luminous'))
    target = target.parentNode;
  if (!target)
    return -1;
  return parseInt(target.id.match(/\d+$/));
}

function luminous_attach_metabar(floating)
{
  

  
//   luminous_fixed_bar = !floating;
  
  if ($Luminous.browser.msie && $Luminous.browser.version <= 7)
    floating = false;
  
  $Luminous('.luminous').each(function (i, e){
    $Luminous('pre.code', $Luminous(e)).addClass('highlighted')
  });  
  
  var bar = $Luminous(metabar_buttons);
  $Luminous(bar).bind('mousedown', function(e){ return false;} );  
  if (floating)
  {
    $Luminous(bar).hide();
    $Luminous(bar).addClass('metabar_buttons_floating');
    
    $Luminous('.luminous').bind('mouseenter', function(e) {
      luminous_show_buttons(luminous_root(e.target));
      
    });
    $Luminous('.luminous').bind('mouseleave', function(e) {  
      luminous_hide_buttons(luminous_root(e.target));
    });
  }
  else
  {    
    bar.addClass('metabar_buttons_fixed');
    bar = $Luminous('<div class="metabar"></div>').append(bar);
  }
  $Luminous('.luminous').prepend(bar);
  if (!floating)
  {
    $Luminous('.luminous').each(function(i, e) {
      var $e = $Luminous(e);
      var len = $Luminous('pre.highlighted', $e).html().replace(/<.*?>/g, "").length;
      
      var nos = $Luminous('pre.line_numbers', $e).children();
      var num_lines = null;
      if (nos.length)
      {
        for (var i=nos.length-1; i >= 0; i--)
        {
          num_lines = parseInt($Luminous(nos[i]).html().replace(/&.*?;|\s/g, ''));
          if (!isNaN(num_lines))
            break;
        }
      }
      if (isNaN(num_lines) || num_lines == null)
        num_lines = $Luminous('pre.highlighted', $e).html().match(/\n/g).length;
      
      len /= 1024.0;
      len = "" + len.toFixed(2);
      
      var h = $e.find('.metabar').html();
      
      
      $e.find('.metabar').prepend(
        $Luminous("<span>Source code | " + num_lines + " lines | " + len + " KiB</span>").css('margin-left', '2px').css('margin-top', '2px').css('display', 'inline-block')
                          );
      var parents = $e.parents();
      var width = $Luminous(parents[0]).width(); 
      for(var i=1; i<parents.length; i++)
        width = Math.min(width, $Luminous(parents[i]).width());
      var diff = $e.width() - width;
      if (diff > 0)
        $e.find('.metabar_buttons').css('right', diff + 'px');

      
    });
  }
  
  $Luminous('.luminous').each(function(i, e) {
    var sh =  $Luminous('div.code_container', e)[0].scrollHeight;
    var h =  $Luminous('div.code_container', e)[0].clientHeight;
    var sw =  $Luminous('div.code_container', e)[0].scrollWidth;
    var w =  $Luminous('div.code_container', e)[0].clientWidth;
    if (sh <= h && sw <= w)
      $Luminous('.luminous_uncollapse_clicker', e).hide();
  });
    
    
  $Luminous('.luminous_uncollapse_clicker').click(function(e) {
    luminous_exp_collapse(luminous_root((e.target)));
    return false;
  });
  
  
  
  $Luminous('.luminous_search_clicker').click(function(e) {
    luminous_search_open(luminous_root((e.target)));
    return false;
  });
  
  $Luminous('.luminous_info_clicker').click(function(e) {
    luminous_show_info(luminous_root((e.target)));
    luminous_hide_buttons(luminous_root((e.target)));    
    return false;
  });
  $Luminous('.luminous_print_clicker').click(function(e) {
    luminous_print(luminous_root((e.target)));
    luminous_hide_buttons(luminous_root((e.target)));
    return false;
  });

  $Luminous('.luminous_plain_clicker').click(function(e) {
    luminous_toggle_plain(luminous_root((e.target)));
    return false;
  });
  $Luminous('.luminous_zoomin_clicker').click(function(e){
    $Luminous(luminous_root(e.target)).fadeTo(200, 0, function() {    
      var size = parseInt($Luminous(this).css('font-size'));
      $Luminous(this).css('font-size', (++size) + 'px');
      $Luminous(this).fadeTo(200, 1);
    });
    return false;
  });
  $Luminous('.luminous_zoomout_clicker').click(function(e){
    var root = luminous_root(e.target);    
    var size = parseInt($Luminous(root).css('font-size'));
    if (size <= 1)
      return false;
    
    $Luminous(root).fadeTo(200, 0, function() { 
      var size = parseInt($Luminous(this).css('font-size'));
      $Luminous(this).css('font-size', (--size) + 'px');
      $Luminous(this).fadeTo(200, 1);
    });
    return false
  });
  
  $Luminous('a.line_number').each(function(i, e) {
    var $e = $Luminous(e);
    $e.click(function(e) {
      var $el = $Luminous(this);
      var name = $el.attr('id').replace(/^lineno/, 'line');
      var target = '#' + name;
      $Luminous(target).toggleClass('highlighted_line');
      return false;
    });
  });  
}

/* On some doctypes Opera will collapse blank lines into height:0,
 * which skews everything.
 * This function prepends any such lines with a space character to prevent
 * this from happening, although it's still not ideal.
 */ 
function luminous_opera_hack()
{
  var bad_doctype = true;
  
  var doctype = document.doctype;
  if (doctype != undefined)
  {
    var text = captureDoctypeType = doctype.publicId;
    var uri = captureDoctypePath = doctype.systemId;
    // Strict doctype - okay
    if (uri.match(/strict\.dtd/))
      bad_doctype = false;
    // HTML 5 doctype - okay
    else if( text.replace(/(^[\s]+)|([\s]+$)/g).toLowerCase() == "html")
      bad_doctype = false;
  }
  
  if (!bad_doctype)
    return;
  
  var d = $Luminous(document).html();
  var x;
  $Luminous('div.luminous').each( function (i, e) {
    $Luminous('span.line', $Luminous(e)).each( function (i, e) {
      var html = $Luminous(e).html();
      if (html.replace(/<.*?>/g, '').replace(/(^[\s]+)|([\s]+$)/g, '') == '')
      {
        $Luminous(e).html("&nbsp;" + html);
      }
    });
  });
}

function luminous_init()
{
  if (!luminous_initialised)
  {
    luminous_attach_metabar(!luminous_fixed_bar);
    if ($Luminous.browser.opera)
      luminous_opera_hack();
  }
  luminous_initialised = true;
}

function Luminous()
{
  var onload = window.onload;
  if (onload != undefined)
  {
    window.onload = function(){    
      onload();
      luminous_init();
    };
  }
  else window.onload = luminous_init;  
}


 

Luminous();


